﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.EisPack
{
    /// <summary>
    /// Forms the eigenvectors of a real general matrix by back transforming those of 
    /// the corresponding balanced matrix determined by BALANC.
    /// </summary>
    [Serializable]
    public static class BalbakClass
    {
        /// <summary>
        /// Forms the eigenvectors of a real general matrix by back transforming those of 
        /// the corresponding balanced matrix determined by BALANC.
        /// </summary>
        /// <param name="n">The n.</param>
        /// <param name="lo">The lo parameter.</param>
        /// <param name="hi">The hi parameter.</param>
        /// <param name="scale">Contains information determining the permutations and scaling factors 
        /// used by BALANC.</param>
        /// <param name="m">The number of columns of Z to be back transformed.</param>
        /// <param name="z">Contains the real and imaginary parts of the eigenvectors to be back 
        /// transformed in its first M columns.</param>
        public static void Balbak(int n, int lo, int hi, double[] scale, int m, double[,] z)
        {
            /* This routine is a translation of the Algol procedure from
             * Handbook for Automatic Computation, vol. II, Linear Algebra,
             * by Wilkinson and Reinsch, Springer-Verlag.
             */
            double s;
            int i, j, k, ii;

            m--; /* m is handled as a FORTRAN index variable */
            if (m == 0)
            {
                goto _200;
            }
            if (hi == lo)
            {
                goto _120;
            }
            for (i = lo; i <= hi; i++)
            {
                s = scale[i];

                /* Left hand eigenvectors are back transformed if the foregoing
                 * statement is replaced by s = 1.0 / scale[i] ...
                 */
                for (j = 0; j <= m; j++)
                {
                    z[i, j] *= s;
                }
            }
            _120:
            for (ii = 0; ii < n;)
            {
                i = ii;
                if ((i >= lo) && (i <= hi))
                {
                    goto _140;
                }
                if (i < lo)
                {
                    i = lo - ii;
                }
                k = (int) scale[i];
                if (k == i)
                {
                    goto _140;
                }
                for (j = 0; j <= m; j++)
                {
                    s = z[i, j];
                    z[i, j] = z[k, j];
                    z[k, j] = s;
                }
                _140:
                return;
            }
            _200:

            return;
        }
    }
}